Namespace Output

    Module mOutput



        Private strServerName As String = "MirEvo Server v" & My.Application.Info.Version.ToString(4)

        Dim buffer(Constants.maxbufferlines - 1) As String
        Dim bufferptr As Integer

        Dim isLocked As Boolean

        Public bNewLines As Boolean

        Public Sub InitConsole()

            On Error Resume Next

            'Console.WindowWidth = Constants.ConsoleWidth + 1
            'Console.WindowHeight = Constants.ConsoleHeight + 1

            Console.BufferWidth = Constants.ConsoleWidth + 1
            Console.BufferHeight = Constants.ConsoleHeight + 1

            For i As Integer = 0 To Constants.maxbufferlines - 1
                buffer(i) = ""
            Next

            bufferptr = 1

        End Sub

        Public Sub AddLine(ByVal msg As String)

            Dim logstr As String = RemoveColorTags(msg)

            Logger.LoggerWriteLine(logstr)
            Debug.WriteLine(logstr)

            Static objLock As New Object

            SyncLock objLock

                Dim tmpmsg As String = ""

                Do

                    tmpmsg = StripFlagsFromLine(msg, 96)

                    'If msg.Contains(vbCrLf) Then
                    'tmpmsg = Left(msg, InStr(msg, vbCrLf) - 1)
                    'msg = Right(msg, (msg.Length - tmpmsg.Length) - 2)
                    'Else
                    'tmpmsg = msg
                    'End If

                    If tmpmsg.Contains(vbCrLf) Then
                        Dim tmpstr As String
                        tmpstr = Left(tmpmsg, InStr(tmpmsg, vbCrLf) - 1)
                        msg = Right(tmpmsg, (tmpmsg.Length - tmpstr.Length) - 2) & msg
                        tmpmsg = tmpstr
                    End If

                    'Do

                    'If tmpmsg.Length > 96 Then
                    'bufferptr += 1
                    'If bufferptr = Constants.maxbufferlines Then bufferptr = 0
                    'buffer(bufferptr) = Left(tmpmsg, 96)
                    'tmpmsg = Right(tmpmsg, tmpmsg.Length - 96)
                    'Else
                    bufferptr += 1
                    If bufferptr = Constants.maxbufferlines Then bufferptr = 0
                    buffer(bufferptr) = tmpmsg
                    'Exit Do
                    'End If

                    'Loop

                Loop Until msg.Length = 0

                bNewLines = True

            End SyncLock

        End Sub

        Private Function RemoveColorTags(ByRef msg As String) As String

            Dim outstr As String = ""
            Dim C As Char
            Dim flagOpen As Boolean

            For i As Integer = 1 To msg.Length

                C = Mid(msg, i, 1)

                Select Case C

                    Case "\"
                        If Not flagOpen Then
                            flagOpen = True
                        Else
                            outstr &= C
                        End If

                    Case "B", "F"
                        If flagOpen Then
                            If IsNumeric(Mid(msg, i + 1, 1)) Then
                                i += 1
                            Else
                                outstr &= "\" & C
                            End If
                            flagOpen = False
                        Else
                            outstr &= C
                        End If

                    Case Else
                        outstr &= C
                        flagOpen = False

                End Select

            Next

            Return outstr

        End Function

        Private Sub WriteLine(str As String)
            Write(str & vbCrLf)
        End Sub

        Private Function StripFlagsFromLine(ByRef str As String, maxlen As Integer) As String

            Dim flagOp As Boolean
            Dim flagForeCol As Boolean
            Dim flagBackCol As Boolean

            Dim out As String = ""
            Dim Count As Integer
            Dim TotalCount As Integer

            For Each C As Char In str.ToCharArray

                If C = "\" Then

                    flagOp = True
                    out &= C

                Else

                    If Not flagOp Then

                        out &= C
                        Count += 1

                    Else

                        If flagForeCol Or flagBackCol Then

                            out &= C
                            flagOp = False
                            flagForeCol = False
                            flagBackCol = False

                        ElseIf C = "F" Then
                            flagForeCol = True
                            out &= C
                        ElseIf C = "B" Then
                            flagBackCol = True
                            out &= C
                        Else
                            out &= ("\" & C)
                            Count += 1
                            flagOp = False
                            flagForeCol = False
                            flagBackCol = False
                        End If

                    End If

                End If

                TotalCount += 1

                If Count = maxlen Then Exit For

            Next

            str = Right(str, str.Length - TotalCount)
            Return out

        End Function

        Private Sub Write(str As String)

            Dim flagOp As Boolean
            Dim flagForeCol As Boolean
            Dim flagBackCol As Boolean

            For Each C As Char In str.ToCharArray

                If C = "\" Then

                    flagOp = True

                Else

                    If Not flagOp Then

                        Console.Write(C)

                    Else

                        If flagForeCol Then

                            Select Case C

                                Case "0"
                                    Console.ForegroundColor = ConsoleColor.White
                                Case "1"
                                    Console.ForegroundColor = ConsoleColor.DarkGray
                                Case "2"
                                    Console.ForegroundColor = ConsoleColor.Green
                                Case "3"
                                    Console.ForegroundColor = ConsoleColor.Red
                                Case "4"
                                    Console.ForegroundColor = ConsoleColor.Yellow
                                Case "5"
                                    Console.ForegroundColor = ConsoleColor.Cyan
                                Case "6"
                                    Console.ForegroundColor = ConsoleColor.Blue
                                Case "7"
                                    Console.ForegroundColor = ConsoleColor.Magenta
                                Case "8"
                                    Console.ForegroundColor = ConsoleColor.Black
                                Case "9"
                                    Console.ForegroundColor = ConsoleColor.DarkRed

                            End Select


                            flagOp = False
                            flagForeCol = False

                        ElseIf flagBackCol Then

                            Select Case C

                                Case "0"
                                    Console.BackgroundColor = ConsoleColor.White
                                Case "1"
                                    Console.BackgroundColor = ConsoleColor.DarkGray
                                Case "2"
                                    Console.BackgroundColor = ConsoleColor.Green
                                Case "3"
                                    Console.BackgroundColor = ConsoleColor.Red
                                Case "4"
                                    Console.BackgroundColor = ConsoleColor.Yellow
                                Case "5"
                                    Console.BackgroundColor = ConsoleColor.Cyan
                                Case "6"
                                    Console.BackgroundColor = ConsoleColor.Blue
                                Case "7"
                                    Console.BackgroundColor = ConsoleColor.Magenta
                                Case "8"
                                    Console.BackgroundColor = ConsoleColor.Black
                                Case "9"
                                    Console.BackgroundColor = ConsoleColor.DarkRed

                            End Select

                            flagOp = False
                            flagBackCol = False

                        ElseIf C = "F" Then
                            flagForeCol = True
                        ElseIf C = "B" Then
                            flagBackCol = True
                        Else
                            Console.Write("\" & C)
                            flagOp = False
                            flagForeCol = False
                            flagBackCol = False
                        End If

                    End If


                End If

            Next

        End Sub

        Public Sub DrawConsole()

            Do Until Not isLocked
                System.Windows.Forms.Application.DoEvents()
                System.Threading.Thread.Sleep(10)
            Loop

            isLocked = True

            Console.Clear()
            Console.SetCursorPosition(0, 0)
            If (Socket.SockServer Is Nothing) Then
                WriteLine("\F9" & strServerName & "\F0")
            Else

                Dim mobcount As Integer
                For idx As Integer = 0 To MirEvoSvr.mMaps.mMaps.Count - 1
                    mobcount += MirEvoSvr.mMaps.mMaps(idx).Mobs.mColMobs.Count
                Next

                WriteLine("\F5" & strServerName & "  \F0server fp/s: \F2" & Globals.iFPS & "  \F0D: \F4" & FormatNumber(Socket.SockServer.DataRateIn, 3) & "\F0Kb/s  U: \F4" & FormatNumber(Socket.SockServer.DataRateOut, 3) & "\F0Kb/s  T: \F3" & FormatNumber(Socket.SockServer.DataTransfered, 3) & "\F0Kb M:\F5" & mobcount)
            End If

            WriteLine("\B0\F1" & StrDup(Console.WindowWidth - 1, "=") & "\F0\B8")


            Dim OutputLines As Integer = Console.WindowHeight - 4
            Dim LinesToDraw As Integer = CalcOutputLines()
            Dim bufferstart As Integer = (bufferptr - LinesToDraw) + 1
            Dim lineswritten As Integer

            If bufferstart < 0 Then
                bufferstart = Constants.maxbufferlines + bufferstart
                For i As Integer = bufferstart To Constants.maxbufferlines - 1
                    WriteLine(buffer(i))
                    lineswritten += MeasureLines(buffer(i))
                    If lineswritten = OutputLines Then
                        Exit For
                    End If
                Next
                If lineswritten < CalcOutputLines() Then
                    For i As Integer = 0 To bufferptr
                        WriteLine(buffer(i))
                        lineswritten += MeasureLines(buffer(i))
                        If lineswritten = OutputLines Then
                            Exit For
                        End If
                    Next
                End If
            Else
                For i As Integer = bufferstart To bufferptr
                    WriteLine(buffer(i))
                    lineswritten += MeasureLines(buffer(i))
                    If lineswritten = OutputLines Then
                        Exit For
                    End If
                Next
            End If

            WriteLine("\B0\F1" & StrDup(Console.WindowWidth - 1, "=") & "\F0\B8")
            Write(">\F1" & Globals.sInput)

            bNewLines = False

            isLocked = False

        End Sub

        Private Function CalcOutputLines()

            Dim currlines As Integer
            Dim max As Integer = Console.WindowHeight - 5

            Dim bufferstart As Integer = bufferptr - (max)
            Dim lineswritten As Integer

            Dim segment As Integer

            If bufferstart < 0 Then
                bufferstart = Constants.maxbufferlines + bufferstart
                For i As Integer = bufferstart To Constants.maxbufferlines - 1
                    segment = MeasureLines(buffer(i))

                    If lineswritten + segment <= max Then
                        lineswritten += segment

                        currlines += 1
                        If lineswritten = max Then
                            Exit For
                        End If
                    Else
                        Exit For
                    End If
                Next
                If lineswritten < max Then
                    For i As Integer = 0 To bufferptr
                        segment = MeasureLines(buffer(i))

                        If lineswritten + segment <= max Then
                            lineswritten += segment

                            currlines += 1
                            If lineswritten = max Then
                                Exit For
                            End If
                        Else
                            Exit For
                        End If
                    Next
                End If
            Else
                For i As Integer = bufferstart To bufferptr
                    segment = MeasureLines(buffer(i))

                    If lineswritten + segment <= max Then
                        lineswritten += segment

                        currlines += 1
                        If lineswritten = max Then
                            Exit For
                        End If
                    Else
                        Exit For
                    End If
                Next
            End If

            Return currlines

        End Function

        Private Function MeasureLines(str As String) As Integer

            Dim c As Integer
            For i = 1 To str.Length

                If Mid(str, i, 1) = "\" Then c += 2
                If i < str.Length And Mid(str, I + 1, 1) = "B" Then c += 1
                If i < str.Length And Mid(str, I + 1, 1) = "F" Then c += 1


            Next

            If str.Length = 0 Then Return 1

            Dim res As Integer = str.Length \ Console.WindowWidth

            If str.Length Mod Console.WindowWidth > 0 Then
                res += 1
            End If

            Return res - c

        End Function

    End Module

End Namespace
